/* chatserv.c
 *
 *  Created on: 2012. 4. 12.
 *      Author: jphong
 */
#include	"unp.h"
#include	"clients.h"
#include	"serv_parse.h"
#include	"debug.h"
#include 	"unpthread.h"

static void *threadCli(void *arg);

int main(int argc, char **argv) {

	Client *client;
	socklen_t clilen;
	struct sockaddr_in cliaddr;
	int listenfd;
	int *connfd;
	pthread_t tid;

	if (argc != 2)
		err_quit("usage: chatserv <service or port>");

	listenfd = Tcp_listen(NULL, argv[1], NULL);

	for (;;) {
		/* new client connection */
		clilen = sizeof(cliaddr);
		connfd = (int *) malloc(sizeof(int));
		*connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);

		debug("connection from %s\n", Sock_ntop((SA *) &cliaddr, clilen));

		if ((client = createClient(*connfd)) == NULL) {
			err_msg("couldn't allocate memory for a client or too many clients");
			Close(*connfd); // Refuse the client's connection
		}

		client->ipaddr = inet_ntoa(cliaddr.sin_addr);

		debug("client->ipaddr : %s\n", client->ipaddr);


		Pthread_create(&tid, NULL, &threadCli, connfd);

	} // End of for loop
}

static void *
threadCli(void *arg) {
	int connfd;
	char request[MAXLINE], response[MAXLINE];
	Client * client;
	int n, temp = 0;

	connfd = *((int *) arg);
	free(arg);
	pthread_detach(pthread_self());


	for (client = getClientList(); client != NULL; client = client->next) {
		if (client->connfd == connfd)
			break;
	}

	while (1) {
		if ((n = readClient(client)) <= 0 && temp == 0) {
			if (n == 0)
				err_msg("%s [%d] abnormally exits", getUser(client), connfd);
			else
				err_ret("%s [%d]: read error", getUser(client), connfd);
			Close(connfd);
			destroyClient(client);
			temp = 1;
		}
		// Get all the methods ending with <CRLF><CRLF> saved in the client's ReadBuffer
		while ((getMessage(client->readBuffer, request, MAXLINE)) > 0) {
			int m;
			debug("--> %s", request);
			m = serv_parse(client, request, response); // parse request and produce response
			if (*response != '\0') {
				writen(connfd, response, strlen(response)); // reply back
				debug("<-- %s", response);
			}
			if (m == 0) { // QUIT received
				debug("%s[%d] exit\n", getUser(client), connfd);
				Close(connfd);
				destroyClient(client);
				pthread_exit((void *)NULL);
			}
		} // end of while loop
	}
	return (NULL);
}

